/**
 * <pre>
 * @(#)ScrollBarView.java 1.00 2009-11-25
 * 
 * Copyright (c) 1998, 2009 Regular Individual. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *    http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * Contributor(s):
 *     Haixu Huang
 * </pre>
 **/
package cn.sh.huang.chart.ext.ui;

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;

import cn.sh.huang.chart.ext.enumtype.ScrollBarType;
import cn.sh.huang.chart.view.View;

/**
 * <pre>
 * ScrollBarView ...
 * 
 * @version 1.0
 * </pre>
 */
public class ScrollBarView extends View
{

    private final ScrollBarType barType;
    private int all, wnd, pos;
    private Image graph;
    private boolean dirtyFlag = true;
    private final ScrollBarUI ui;

    public ScrollBarView(ScrollBarType barType, ScrollBarUI ui)
    {
        this.barType = barType;
        this.ui = ui;
    }

    final private void recycleGraph()
    {
        if (graph != null) {
            graph.getGraphics().dispose();
            graph = null;
            System.gc();
        }
    }

    public void dispose()
    {
        recycleGraph();
        super.dispose();
    }

    public void setViewSize(final int width, final int height)
    {
        if (width == 0 || height == 0) {
            pos = 0;
        }
        super.setViewSize(width, height);
    }

    public void setLength(int all, int wnd)
    {
        if (pos + wnd > all) {
            pos = all - wnd;
        }
        this.all = all;
        this.wnd = wnd;
        dirtyFlag = true;
    }

    public void setPosition(int pos)
    {
        this.pos = pos;
        dirtyFlag = true;
    }

    public Dimension getMinimumSize()
    {
        return null;
    }

    public Dimension getPreferredSize()
    {
        return null;
    }

    private int[] translateMousePoint(Point mousePoint)
    {
        Dimension viewSize = getViewSize();
        Point viewAnchor = this.getViewAnchor();
        mousePoint.translate(-viewAnchor.x, -viewAnchor.y);
        int u = 100, v = 0, w = -1;
        if (barType.equals(ScrollBarType.HORIZONTAL)) {
            u = viewSize.width;
            v = mousePoint.x;
            w = mousePoint.y;
        } else {
            u = viewSize.height;
            v = mousePoint.y;
            w = mousePoint.x;
        }
        return new int[] { u, v, w };
    }

    public void mousePressed(MouseEvent e)
    {
        int[] uv = translateMousePoint(e.getPoint());
        ui.onScroll(barType, all, wnd, pos, uv[0], uv[1]);
    }

    public void mouseReleased(MouseEvent e)
    {
        ui.offScroll(barType);
    }

    public void mouseDragged(MouseEvent e)
    {
        int[] uv = translateMousePoint(e.getPoint());
        ui.thumbScroll(barType, all, wnd, uv[0], uv[1], uv[2]);
    }

    /*
     * (non-Javadoc)
     * @see cn.sh.huang.chart.view.AbstractView#render(java.awt.Graphics2D)
     */
    public void render(Graphics2D g2d)
    {
        renderGraph();
        Point viewAnchor = getViewAnchor();
        Rectangle viewRect = getViewRect();
        int rx = viewRect.x, ry = viewRect.y, rw = viewRect.width, rh = viewRect.height;
        int vx = viewAnchor.x, vy = viewAnchor.y, vw = graph.getWidth(null), vh = graph.getHeight(null);
        if (vx > rx + rw || vx + vw < rx || vy > ry + rh || vy + vh < ry) { // view area is out the rendering area
            return;
        }
        int sx = vx - rx, sy = vy - ry;
        g2d.drawImage(graph, rx, ry, rx + rw, ry + rh, sx, sy, sx + rw, sy + rh, null);
    }

    private void renderGraph()
    {
        Dimension viewSize = getViewSize();
        if (graph == null || graph.getWidth(null) != viewSize.width || graph.getHeight(null) != viewSize.height) {
            recycleGraph();
            graph = new BufferedImage(viewSize.width, viewSize.height, BufferedImage.TYPE_INT_ARGB);
            dirtyFlag = true;
        }
        if (dirtyFlag) {
            Graphics2D g2d = (Graphics2D) graph.getGraphics();
            if (barType.equals(ScrollBarType.HORIZONTAL)) {
                ui.renderHBar(g2d, new Rectangle(new Point(0, 0), viewSize), all, wnd, pos);
            } else {
                ui.renderVBar(g2d, new Rectangle(new Point(0, 0), viewSize), all, wnd, pos);
            }
            dirtyFlag = false;
        }
    }
}
